package org.aldar.bquest.logic.controller.board;

import org.aldar.bquest.constants.IConstants;
import org.aldar.bquest.constants.LandscapeType;
import org.aldar.bquest.entity.TileSprite;
import org.aldar.bquest.logic.controller.entity.TileBoard;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
 * User: Daria
 * Date: 5/31/13 8:07 PM
 */
public class MatchedTilesFinder implements IConstants {

    private static TileSprite getAdjacentTile(int tileRow, int tileCol, int difRow, int difCol) {
        return TileBoard.tileMap.get(TileBoard.getKey(tileRow + difRow, tileCol + difCol));
    }

    private static TileSprite getMatchedAdjacentTile(TileSprite tile, int tileRow, int tileCol, int difRow, int difCol) {
        tile.setCurrentCol(tileCol);
        tile.setCurrentRow(tileRow); //will be used in removeMatchedTiles method in class AfterMatchProcessor
        TileSprite adjacentTile = getAdjacentTile(tileRow, tileCol, difRow, difCol);
        if (adjacentTile != null && LandscapeType.allowMatch(adjacentTile.getStyle(), tile.getStyle())) {
            return adjacentTile;
        }
        return null;
    }

    private static ArrayList<TileSprite> checkDiagonalVertical(int curColInit, int curRowInit) {
        return getAdjacentMatches(curRowInit, curColInit, 1, 1);
    }

    private static ArrayList<TileSprite> checkDiagonalHorizontal(int curColInit, int curRowInit) {
        return getAdjacentMatches(curRowInit, curColInit, -1, 1);
    }

    private static ArrayList<TileSprite> checkHorizontal(int curColInit, int curRowInit) {
        return getAdjacentMatches(curRowInit, curColInit, 0, 1);
    }

    private static ArrayList<TileSprite> checkVertical(int curColInit, int curRowInit) {
        return getAdjacentMatches(curRowInit, curColInit, 1, 0);
    }

    public static boolean isTileInMatch(int col, int row) {
        return ((checkHorizontal(col, row).size() >= 3) ||
                (checkVertical(col, row).size() >= 3) /*||
                (checkDiagonalHorizontal(col, row).size() >= 3) ||
                (checkDiagonalVertical(col, row).size() >= 3)*/);
    }

    private static ArrayList<TileSprite> getAdjacentMatches(int curRowInit, int curColInit, int dir1RowDif, int dir1ColDif) {
        ArrayList<TileSprite> deadArrayList = new ArrayList<TileSprite>();
        TileSprite tile = TileBoard.tileMap.get(TileBoard.getKey(curRowInit, curColInit));
        if (tile == null) {
            return deadArrayList;
        }
        deadArrayList.add(tile);
        TileSprite adjTile = tile;
        int curRow = curRowInit;
        int curCol = curColInit;
        while ((adjTile = getMatchedAdjacentTile(adjTile, curRow, curCol, dir1RowDif, dir1ColDif)) != null) {
            curRow += dir1RowDif;
            curCol += dir1ColDif;
            deadArrayList.add(adjTile);
        }
        adjTile = tile;
        curRow = curRowInit;
        curCol = curColInit;
        while ((adjTile = getMatchedAdjacentTile(adjTile, curRow, curCol, dir1RowDif * -1, dir1ColDif * -1)) != null) {
            curRow += dir1RowDif * -1;
            curCol += dir1ColDif * -1;
            deadArrayList.add(adjTile);
        }
        return deadArrayList;
    }

    public static Set<TileSprite> getAllMatchedTilesFor(int col, int row) {
        Set<TileSprite> result = new HashSet<TileSprite>();
        Collection<TileSprite> matches = null;
        if ((matches = checkHorizontal(col, row)).size() >= 3) {
            result.addAll(matches);
        }
        if ((matches = checkVertical(col, row)).size() >= 3) {
            result.addAll(matches);
        }
        /*
        if ((matches = checkDiagonalHorizontal(col, row)).size() >= 3) {
            result.addAll(matches);
        }
        if ((matches = checkDiagonalVertical(col, row)).size() >= 3) {
            result.addAll(matches);
        }
        */
        return result;
    }
}
